package org.linlinjava.litemall.wx.web;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.user.XxlSsoUser;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.admin.service.AdminBillService;
import org.linlinjava.litemall.core.task.TaskService;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.OrderConstant;
import org.linlinjava.litemall.wx.service.WxOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 订单
 */
@RestController
@RequestMapping("/wx/order")
//@Validated
public class WxOrderController {
 private  final Log log= LogFactory.getLog(WxOrderController.class);
    @Autowired
    private LitemallOrderService orderService;
    @Autowired
    private LitemallOrderGoodsService orderGoodsService;
    @Autowired
    private LitemallAddressService addressService;
    @Autowired
    private LitemallCouponService couponService;
    @Autowired
    private CouponVerifyService couponVerifyService;
    @Autowired
    private LitemallCommodityService commodityService;
    @Autowired
    private WxOrderService wxOrderService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private LitemallCartService cartService;
    @Autowired
    private LitemallOrderReportService reportService;
    @Resource
    private AdminBillService adminBillService;

    //常用数字1
    private static final Integer  NO_1 = 1;
    /**
     * 票据类型Type  的三种类型..如果不满足 ,报错
     */
    private static final String  INVOICE_NO1 = String.valueOf(1);
    private static final String  INVOICE_NO2 =String.valueOf(2);
    private static final String  INVOICE_NO3 = String.valueOf(3);
    //保险比率
    private static final String  INSURANCE_RATE = String.valueOf(0.05);

    /**
     * 未付款.订单  订单状态   待确认--201   待付款--202      待到款--203    待检测--204*      待验收--205
     * @param body
     * @param request
     * @return
     */
    @PostMapping("list")
    public Object list(@RequestBody String body, HttpServletRequest request) {
        XxlSsoUser currentUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        if (currentUser == null) {return ResponseUtil.unauthz();}
        String userId = currentUser.getUserid();
        Short state = JacksonUtil.parseShort(body, "state");
        //String sort = JacksonUtil.parseString(body, "sort");
        String sort = "update_time desc";
        String condition = JacksonUtil.parseString(body, "condition");
        Integer page = JacksonUtil.parseInteger(body, "page");
        Integer pageSize = JacksonUtil.parseInteger(body, "pageSize");
        if (page == null || pageSize == null || StringUtils.isEmpty(userId)) {
            return ResponseUtil.badArgument();
        }
        if (page < NO_1 || pageSize < NO_1) {
            return ResponseUtil.badArgumentValue();
        }
        PageInfo<LitemallOrder> pageInfo = orderService.list(Integer.parseInt(userId), state, page, pageSize, sort, condition);
        List<LitemallOrder> list = pageInfo.getList();

        for (LitemallOrder order : list) {
            Map<String, Object> map = new LinkedHashMap<>();
            List<LitemallOrderGoods> goodsList = orderGoodsService.queryByOid(order.getId());
            LocalDateTime confirmTime = order.getConfirmTime();
            LocalDateTime payCreateTime = order.getPayCreateTime();
            if (confirmTime != null) {
                //订单确认时间  加24 小时
                order.setConfirmTime(confirmTime.plusHours(24));
            }
            if (payCreateTime != null) {
                //支付完成时间  加2个小时
                order.setPayCreateTime(payCreateTime.plusHours(2));
            }

            map.put("commodityNum", goodsList.size());
            map.put("commodity", goodsList);
            order.setDetailInfo(map);
        }
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("totalNum", pageInfo.getTotal());
        map.put("orderList", list);
        return ResponseUtil.ok(map);
    }

    /**
     * 保险金额
     * @param body   orderId 订单ID
     * @return
     */
    @PostMapping("insuranceAmount")
    public Object insuranceAmount(@RequestBody String body) {
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        LitemallOrder order = orderService.findById(orderId);
        BigDecimal actualPrice = order.getActualPrice();
        if (actualPrice != null) {
            BigDecimal rate = new BigDecimal(INSURANCE_RATE);
            BigDecimal insuranceAmount = actualPrice.multiply(rate).setScale(2, BigDecimal.ROUND_HALF_UP);
            return ResponseUtil.ok(insuranceAmount);
        }
        return ResponseUtil.ok();
    }

    /**
     * 保险   放入数据库 goods_price 保存
     * @param body   orderId 订单ID
     * @param request
     * @return
     */
    @PostMapping("insurance")
    public Object insurance(@RequestBody String body, HttpServletRequest request) {
        Integer orderId = JacksonUtil.parseInteger(body, "orderId");
        LitemallOrder order = orderService.findById(orderId);
        XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        Integer userId = Integer.parseInt(user.getUserid());
        if (!userId.equals(order.getUserId())) {
            return ResponseUtil.unauthz();
        }
        BigDecimal actualPrice = order.getActualPrice();
        if (actualPrice == null) {
            return ResponseUtil.badArgumentValue();
        }
        //保险比率
        BigDecimal rate = new BigDecimal(INSURANCE_RATE);
        BigDecimal insuranceAmount = actualPrice.multiply(rate).setScale(2, BigDecimal.ROUND_HALF_UP);
        order.setGoodsPrice(insuranceAmount);
       // order.setActualPrice(insuranceAmount.add());
        //给前端计算.总价+保险的价格
        BigDecimal  insuranceAndActual= order.getActualPrice().add(order.getGoodsPrice());
        orderService.updateWithOptimisticLocker(order);
        //返回Map
        Map<String,BigDecimal> map=new HashMap<>();
        map.put("insuranceAndActualPrice",insuranceAndActual);
        return ResponseUtil.ok(map);
    }

    /**
     * 详情
     * @param body
     * @param request
     * @return
     */
    @PostMapping("detail")
    public Object detail(@RequestBody String body, HttpServletRequest request) {
        Integer id = JacksonUtil.parseInteger(body, "id");
        if (id == null || id < 1) {
            return ResponseUtil.badArgument();
        }
        LitemallOrder order = orderService.findById(id);
        LocalDateTime confirmTime = order.getConfirmTime();
        LocalDateTime payCreateTime = order.getPayCreateTime();
        if (confirmTime != null) {
            order.setConfirmTime(confirmTime.plusHours(24));
        }
        if (payCreateTime != null) {
            order.setPayCreateTime(payCreateTime.plusHours(2));
        }
        if (order.getUserId().toString().equals(((XxlSsoUser) request.getAttribute(Conf.SSO_USER)).getUserid())) {
            List<LitemallOrderGoods> goodsList = orderGoodsService.queryByOid(order.getId());
            List<LitemallOrderReport> reportList = reportService.queryByOid(order.getId());
           //2020.05.08 计算订单中 订单商品的 总 价格
            BigDecimal orderTotalPrice = orderGoodsService.orderAllGoodsPrice(order.getId());
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("commodityNum", goodsList.size());
            map.put("reportNum", reportList.size());
            map.put("order", order);
            map.put("report", reportList);
            map.put("commodity", goodsList);
            //2020.05.08 接收前端传来总价
            map.put("orderTotalPrice", orderTotalPrice);
            return ResponseUtil.ok(map);
        } else {
            return ResponseUtil.unauthz();
        }
    }

    /**
     * 提交: 接收前端传来的总价 ..保存    // order.setOrderPrice();
     * @param body
     * @param request
     * @return
     */
    @PostMapping("submit")
    public Object submit(@RequestBody String body, HttpServletRequest request) {
        XxlSsoUser user = (XxlSsoUser) (request.getAttribute(Conf.SSO_USER));
        if (user == null) {
            return ResponseUtil.unlogin();
        }
        System.out.println("body>>>" + body);
        LitemallOrder order = parseOrder(body);
        int userId = Integer.parseInt(user.getUserid());
        JSONObject object = JSONObject.parseObject(body);
        String goodsListString = object.getString("goodsList");
        //前端算好总价....传进来
        String priceTotal = object.getString("priceTotal");
        if(StringUtils.isEmpty(priceTotal)){priceTotal="0";}
         //提交订单必须传后台总价..后台保存
        List<LitemallOrderGoods> goodsList = JSONObject.parseArray(goodsListString, LitemallOrderGoods.class);
        if (goodsList == null || goodsList.size() < NO_1) {
            return ResponseUtil.badArgument();
        }
        List<Integer> goodsIdList = new LinkedList<>();
        Map<Integer, List<LitemallOrderGoods>> map = splitOrderGoods(goodsList);
        for (Integer brandId : map.keySet()) {
            order.setId(null);
            order.setOrderStatus(OrderConstant.SUBMITTED);
            order.setUserId(userId);
            order.setBrandId(brandId);
            //设订单总价..前端传
           order.setOrderPrice(new BigDecimal(priceTotal));
            System.out.println();
            orderService.add(order);
            for (LitemallOrderGoods goods : map.get(brandId))  {
                goodsIdList.add(goods.getGoodsId());
                goods.setOrderId(order.getId());
                orderGoodsService.add(goods);
            }
        }
        // 订单支付超期任务
        //taskService.addTask(new OrderUnpaidTask(order.getId()));
        cartService.delete(goodsIdList, userId);
        return ResponseUtil.ok();
    }

    /**
     * 完结订单  同时创建与霜林科技结算单bill
     * @param body
     * @param request
     * @return
     */
    @PostMapping("complete")
    public Object complete(@RequestBody String body, HttpServletRequest request) {
        XxlSsoUser user = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        Integer userId = Integer.parseInt(user.getUserid());
        Integer orderId = JacksonUtil.parseInteger(body, "id");
        if (orderId == null) {
            return ResponseUtil.badArgument();
        }
        LitemallOrder order = orderService.findById(orderId);
        if (!order.getUserId().equals(userId)) {
            return ResponseUtil.unauthz();
        }
        if (!order.getOrderStatus().equals(OrderConstant.ASSAYED)) {
            return ResponseUtil.badArgumentValue();
        }
        order.setOrderStatus(OrderConstant.COMPLETED);
        order.setEndTime(LocalDateTime.now());
        orderService.updateWithOptimisticLocker(order);
        orderGoodsService.completeOrder(order.getId());
        //只有完结状态 (订单状态200)  才 创建结算单
        adminBillService.create(order);
        return ResponseUtil.ok();
    }

    /**
     * 取消
     * @param body
     * @param request
     * @return
     */
    @PostMapping("cancel")
    public Object cancel(@RequestBody String body, HttpServletRequest request) {
        return wxOrderService.update(body, request, new Short[]{OrderConstant.SUBMITTED, OrderConstant.CONFIRMED}, OrderConstant.CANCELED);
    }

    //@PostMapping("refund")
    public Object refund(@RequestBody String body, HttpServletRequest request) {
        return wxOrderService.refund(body, request);
    }

    //@PostMapping("refundUndo")
    public Object refundUndo(@RequestBody String body, HttpServletRequest request) {
        return wxOrderService.refundUndo(body, request);
    }

    //@PostMapping("refundPart")
    public Object refundPart(@RequestBody String body, HttpServletRequest request) {
        return wxOrderService.refundPart(body, request);
    }

    //@PostMapping("refundPartUndo")
    public Object refundPartUndo(@RequestBody String body, HttpServletRequest request) {
        return wxOrderService.refundPartUndo(body, request);
    }

    /**
     * 解析订单  同时验证 票据信息
     * @param body
     * @return
     */
    private LitemallOrder parseOrder(String body) {
        LitemallOrder order = new LitemallOrder();

        String phone = JacksonUtil.parseString(body, "phone");
        Integer addressId = JacksonUtil.parseInteger(body, "addressId");
        String address = JacksonUtil.parseString(body, "address");
        String message = JacksonUtil.parseString(body, "message");
        String mail = JacksonUtil.parseString(body, "mail");
        String consignee = JacksonUtil.parseString(body, "consignee");

        //票据7项
        String invoiceType = JacksonUtil.parseString(body, "invoiceType");
        String invoiceTitle = JacksonUtil.parseString(body, "invoiceTitle");
        String invoiceNo = JacksonUtil.parseString(body, "invoiceNo");
        String invoiceAddress = JacksonUtil.parseString(body, "invoiceAddress");
        String invoicePhone = JacksonUtil.parseString(body, "invoicePhone");
        String invoiceBank = JacksonUtil.parseString(body, "invoiceBank");
        String invoiceAccount = JacksonUtil.parseString(body, "invoiceAccount");
        //新增验证票据信息.. 如果正确继续执行
        validateInvoice(invoiceType, invoiceTitle, invoiceNo, invoiceAddress, invoicePhone, invoiceBank, invoiceAccount);

        if (addressId != null) {
            LitemallAddress a = addressService.findById(addressId);
            address = a.getProvince() + a.getCity() + a.getCounty() + a.getAddressDetail();
            phone = a.getTel();
            consignee = a.getName();
        }

        String orderSn=new SimpleDateFormat("yyHHddmmMMSSS").format(new Date()) + (int) (Math.random() * (9999 - 1000 + 1) + 1000);
        order.setOrderSn(orderSn);
        order.setAddTime(LocalDateTime.now());
        order.setConsignee(consignee);
        order.setAddress(address);
        order.setMobile(phone);
        order.setMessage(message);
        order.setMail(mail);
        order.setInvoiceTitle(invoiceTitle);
        order.setInvoiceNo(invoiceNo);
        order.setInvoiceAddress(invoiceAddress);
        order.setInvoicePhone(invoicePhone);
        order.setInvoiceBank(invoiceBank);
        order.setInvoiceAccount(invoiceAccount);
        order.setInvoiceType(invoiceType);
        return order;
    }

    /**
     * 切割  list 商品.
     * @param list
     * @return
     */
    private Map<Integer, List<LitemallOrderGoods>> splitOrderGoods(List<LitemallOrderGoods> list) {
        Map<Integer, List<LitemallOrderGoods>> map = new LinkedHashMap<>();
        for (LitemallOrderGoods goods : list) {
            LitemallCommodity commodity = commodityService.selectById(goods.getGoodsId());
            goods.setGoodsName(commodity.getCommodityName());
            goods.setPicUrl(commodity.getCommodityMainImage());
            //订单  GoodsPriceOrigin 商品原价   :商品的价格
            goods.setGoodsPriceOrigin(commodity.getCommodityPrice());
            int brandId = commodity.getBrandId();
            if (!map.containsKey(brandId)) {
                List<LitemallOrderGoods> temp = new LinkedList<>();
                temp.add(goods);
                map.put(brandId, temp);
            }
            else {
                List<LitemallOrderGoods> temp = map.get(brandId);
                temp.add(goods);
                map.put(brandId, temp);
            }
        }
        return map;
    }
/*    //显示 个状态下的 数量
    @GetMapping("/eachCount")
    public Object eachCount( HttpServletRequest request) {
        XxlSsoUser currentUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        if (currentUser == null) {
            return ResponseUtil.unauthz();
        }
        String userId = currentUser.getUserid();

        //String sort = JacksonUtil.parseString(body, "sort");
        String sort = "update_time desc";
        Integer page = 1;
        Integer pageSize = 100;

        PageInfo<LitemallOrder> pageInfo = orderService.list(Integer.parseInt(userId), state, page, pageSize, sort, condition);


      *//*  List<LitemallOrder> list = pageInfo.getList();
        for (LitemallOrder order : list) {
            Map<String, Object> map = new LinkedHashMap<>();
            List<LitemallOrderGoods> goodsList = orderGoodsService.queryByOid(order.getId());
            LocalDateTime confirmTime = order.getConfirmTime();
            LocalDateTime payCreateTime = order.getPayCreateTime();
            if (confirmTime != null) {
                order.setConfirmTime(confirmTime.plusHours(24));
            }
            if (payCreateTime != null) {
                order.setPayCreateTime(payCreateTime.plusHours(2));
            }
            map.put("commodityNum", goodsList.size());
            map.put("commodity", goodsList);
            order.setDetailInfo(map);
        }*//*
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("totalNum", pageInfo.getTotal());
        map.put("orderList", list);
        return ResponseUtil.ok(map);
    }*/


    private Boolean validateInvoice(String invoiceType,String invoiceTitle,String invoiceNo,String invoiceAddress,
                                 String invoicePhone,String invoiceBank,String invoiceAccount ){
        //2020.5.10.票据验证信息.双重验证...同/wx/orderInvoice/add  防止旧接口一起提交出错.
        //发票抬头::是1个人或2公司 3 增值(之前定义的)
        //如果 是Type1普通发票/个人   {"invoiceTitle":"个人名称可以不写","invoiceType":"1"}
        if(StringUtils.isEmpty(invoiceType) ||  !INVOICE_NO1.equals(invoiceType)
                && !INVOICE_NO2.equals(invoiceType) &&  !INVOICE_NO3.equals(invoiceType)
        ){ throw new  RuntimeException("请确认票据类别");}

        //普通票个人..不能有其他信息进来
        System.out.println("票据类型为个人>>>" + invoiceType);
        if( INVOICE_NO1.equals(invoiceType)){
            //普通票个人..不能有其他信息进来
            System.out.println("普通发票>>>>>>个人>>>>>" + invoiceType);
            if(StringUtils.isNotEmpty(invoiceNo) || StringUtils.isNotEmpty(invoiceAddress) || StringUtils.isNotEmpty(invoicePhone)
                    ||  StringUtils.isNotEmpty(invoiceBank) ||  StringUtils.isNotEmpty(invoiceAccount)  ){
                throw new  RuntimeException("个人发票不能携带出名称外其他信息");
            }
            invoiceType = INVOICE_NO1;
            //如果 票据抬头不为空..则不能超过20位
            if(StringUtils.isNotEmpty(invoiceTitle)){
                if(invoiceTitle.length() >20){
                    throw new  RuntimeException("不能超过20位");
                }
            }
        }

        //Type2普通发票/公司:::   {"invoiceTitle":"的","invoiceNo":"123123","invoiceType":"2"}
        if( INVOICE_NO2.equals(invoiceType)){
            if(StringUtils.isEmpty(invoiceTitle)){
                throw new  RuntimeException( "公司名称不能为空");
            }
            if(StringUtils.isEmpty(invoiceNo)){
                throw new  RuntimeException( "发票税号不能为空");
            }
            boolean invoiceNoLegal = invoiceNo.length() != 15 && invoiceNo.length() != 18 && invoiceNo.length() != 20;
            if(invoiceNoLegal){
                throw new  RuntimeException( "请确认发票税号位数:15(旧),18(新)或20(特殊)");
            }
            if( StringUtils.isNotEmpty(invoiceAddress) || StringUtils.isNotEmpty(invoicePhone)
                    ||  StringUtils.isNotEmpty(invoiceBank) ||  StringUtils.isNotEmpty(invoiceAccount)  ){
                throw new  RuntimeException( "公司票据信息除了名称/税号,不能携带其他信息");
            }
        }
        //Typ3增值税专用发票  全部数据
        if(INVOICE_NO3.equals(invoiceType)){
            System.out.println("增值税发票>>>>>>进入>>>>>");
            if(StringUtils.isEmpty(invoiceTitle)){throw new  RuntimeException( "发票抬头:个人/公司名称"); }
            //税号一般分为 15. 18(最常见) 20 位(增值见)..&&只要有一个条件不一样就是不满足
            if(StringUtils.isEmpty(invoiceNo)){
                throw new  RuntimeException( "发票税号不能为空");
            }
            boolean invoiceNoLegal = invoiceNo.length() != 15 && invoiceNo.length() != 18 && invoiceNo.length() != 20;
            if(invoiceNoLegal){
                throw new  RuntimeException( "请确认发票税号位数:15(旧),18(新)或20(特殊)");
            }
            //发票地址,个人/公司地址,XX省XX市XX县/区
            if(StringUtils.isEmpty(invoiceAddress) || invoiceAddress.length() < 10 ){
                throw new  RuntimeException( "请确认个人/公司地址,不少于10个字");
            }
            if (!RegexUtil.isMobileExact(invoicePhone)) { throw new  RuntimeException( "手机号格式不正确");}
            //开户行:中国XX银行股份有限公司XX支行
            if(StringUtils.isEmpty(invoiceBank) || invoiceBank.length() <= 6 ){
                throw new  RuntimeException("开户行:中国XX银行股份有限公司XX支行"); }
            //银行账户长度::银行卡规范个人银行卡长度范围13-19位，企业对公账号银行卡范围，前不久看到的长度范围最少8位，最多28位
            if(StringUtils.isEmpty(invoiceAccount) || invoiceAccount.length() <= 8 ){
                throw new  RuntimeException( "银行账户长度不得少于8位"); }
        }
        return true;
    }
}